package com.gitee.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gitee.bo.AdminBo;
import com.gitee.bo.AdminInfoBo;
import com.gitee.bo.AdminPasswordBo;
import com.gitee.enums.ResponseEnum;
import com.gitee.exception.AdminException;
import com.gitee.mapper.AdminMapper;
import com.gitee.pojo.Admin;
import com.gitee.pojo.AdminRole;
import com.gitee.service.IAdminRoleService;
import com.gitee.service.IAdminService;
import com.gitee.vo.AdminVo;
import com.gitee.vo.PageVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements UserDetailsService, IAdminService {

    @Autowired
    private AdminMapper adminMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private IAdminRoleService adminRoleService;


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        AdminVo adminVo = adminMapper.selectByUsername(username);
        if (adminVo == null) {
            throw new UsernameNotFoundException(ResponseEnum.USERNAME_PASSWORD_ERROR.getDesc());
        }
        return adminVo;
    }

    /**
     * 查询后台用户
     *
     * @param keywords
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public PageVo<AdminVo> pageAdmin(String keywords, Integer pageNum, Integer pageSize) {
        List<AdminVo> adminVos = adminMapper.selectByNickName((pageNum - 1) * pageSize, pageSize, keywords);
        LambdaQueryWrapper<Admin> queryWrapper = new QueryWrapper<Admin>().lambda()
                .like(!StrUtil.isBlank(keywords), Admin::getNickName, keywords);
        Integer total = super.count(queryWrapper);
        return new PageVo<>(adminVos, total);
    }

    /**+
     * 新增后台用户
     *
     * @param adminBo
     * @return
     */
    @Transactional
    @Override
    public Boolean addAdmin(AdminBo adminBo) {
        LambdaQueryWrapper<Admin> wrapper = new QueryWrapper<Admin>().lambda().eq(Admin::getUsername, adminBo.getUsername());
        if (super.count(wrapper) > 0) {
            throw new AdminException(ResponseEnum.EXIST_USER);
        }
        Admin admin = new Admin();
        adminBo.setPassword(passwordEncoder.encode(adminBo.getPassword()));
        BeanUtils.copyProperties(adminBo, admin);
        super.save(admin);
        List<AdminRole> adminRoles = adminBo.getRoleIds().stream().map(roleId -> {
            AdminRole adminRole = new AdminRole();
            adminRole.setAdminId(admin.getId());
            adminRole.setRoleId(roleId);
            return adminRole;
        }).collect(Collectors.toList());
        return adminRoleService.saveBatch(adminRoles);
    }

    /**
     * 管理员更新用户信息，不修改密码
     *
     * @param adminBo
     * @return
     */
    @Transactional
    @Override
    public Boolean updateAdmin(AdminBo adminBo, Integer adminId) {
        Admin admin = new Admin();
        adminBo.setPassword(null);
        BeanUtils.copyProperties(adminBo, admin);
        admin.setId(adminId);
        super.updateById(admin);
        adminRoleService.deleteByAdminId(adminId);
        List<AdminRole> adminRoles = adminBo.getRoleIds().stream().map(roleId -> {
            AdminRole adminRole = new AdminRole();
            adminRole.setAdminId(admin.getId());
            adminRole.setRoleId(roleId);
            return adminRole;
        }).collect(Collectors.toList());
        return adminRoleService.saveBatch(adminRoles);
    }

    /**
     * 后台用户自己更新信息
     *
     * @param adminInfoBo
     * @param adminId
     * @return
     */
    @Transactional
    @Override
    public Boolean updateAdminInfo(AdminInfoBo adminInfoBo, Integer adminId) {
        Admin admin = new Admin();
        BeanUtils.copyProperties(adminInfoBo, admin);
        admin.setId(adminId);
        return super.updateById(admin);
    }

    /**
     * 用户自己修改密码
     *
     * @param adminPasswordBo
     * @return
     */
    @Transactional
    @Override
    public Boolean updateAdminPassword(AdminPasswordBo adminPasswordBo,Integer adminId) {
        Admin admin = super.getById(adminId);
        if (admin == null) {
            throw new AdminException(ResponseEnum.NO_USER);
        }
        if (!passwordEncoder.matches(adminPasswordBo.getOldPassword(), admin.getPassword())) {
            throw new AdminException(ResponseEnum.PASSWORD_ERROR);
        }
        LambdaUpdateWrapper<Admin> updateWrapper = new UpdateWrapper<Admin>()
                .lambda().set(Admin::getPassword, passwordEncoder.encode(adminPasswordBo.getNewPassword()))
                .eq(Admin::getId, adminId);

        return super.update(updateWrapper);
    }

    /**
     * 删除后台用户及其关联的角色
     *
     * @param adminId
     * @return
     */
    @Transactional
    @Override
    public Boolean deleteAdmin(Integer adminId) {
        return super.removeById(adminId) && adminRoleService.deleteByAdminId(adminId);
    }

    /**
     * 批量删除用户机器关联的角色
     *
     * @param adminIds
     * @return
     */
    @Transactional
    @Override
    public Boolean deleteAdminBatch(Integer[] adminIds) {
        return super.removeByIds(Arrays.asList(adminIds)) && adminRoleService.deleteByAdminIds(adminIds);
    }
}
